package com.ant.collect.excel;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExcelTreeBuilder {
    // 节点类：存储节点信息和子节点
    static class Node {
        private String code;       // 对应 dic_value
        private String name;       // 对应 dic_name
        private int level;         // 对应 dic_type + 1
        private String parentId;   // 父节点 code
        private List<Node> children = new ArrayList<>(); // 子节点列表

        public Node(String code, String name, int level) {
            this.code = code;
            this.name = name;
            this.level = level;
        }

        // 添加子节点
        public void addChild(Node child) {
            this.children.add(child);
        }

        // getter 方法
        public String getCode() { return code; }
        public String getName() { return name; }
        public int getLevel() { return level; }
        public String getParentId() { return parentId; }
        public void setParentId(String parentId) { this.parentId = parentId; }
        public List<Node> getChildren() { return children; }
    }

    public static void main(String[] args) {
        String inputFilePath = "f:/hb/321.xls"; // 输入Excel路径
        try {
            // 1. 读取Excel数据并转换为节点列表
            List<Node> allNodes = readExcelToNodes(inputFilePath);

            // 2. 构建树形结构
            Node root = buildTree(allNodes);

            // 3. 打印树形结构（测试用）
            printTree(root, 0);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 读取Excel并转换为节点列表
    private static List<Node> readExcelToNodes(String filePath) throws IOException {
        List<Node> nodes = new ArrayList<>();
        Workbook workbook = getWorkbook(filePath);
        Sheet sheet = workbook.getSheetAt(0); // 读取第一个工作表

        // 跳过表头（假设表头在第0行）
        for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row == null) continue;

            // 读取字段（根据图片列索引：dic_name在第2列，dic_value在第3列，dic_type在第4列）
            String dicName = getCellValue(row.getCell(1)); // dic_name（索引1）
            String dicValue = getCellValue(row.getCell(2)); // dic_value（索引2）
            String dicTypeStr = getCellValue(row.getCell(3)); // dic_type（索引3）

            // 过滤无效数据
            if (dicName.isEmpty() || dicValue.isEmpty() || dicTypeStr.isEmpty()) {
                continue;
            }

            // 转换dic_type为整数，计算level
            int dicType;
            try {
                dicType = Integer.parseInt(dicTypeStr);
            } catch (NumberFormatException e) {
                System.out.println("行" + rowNum + "的dic_type格式错误：" + dicTypeStr);
                continue;
            }
            int level = dicType + 1;

            // 添加节点
            nodes.add(new Node(dicValue, dicName, level));
        }
        workbook.close();
        return nodes;
    }

    // 构建树形结构
    private static Node buildTree(List<Node> allNodes) {
        // 1. 按dic_type分组（key：dic_type，value：该层级的所有节点）
        Map<Integer, List<Node>> typeToNodes = new HashMap<>();
        for (Node node : allNodes) {
            int dicType = node.getLevel() - 1; // level = dic_type + 1 → dic_type = level - 1
            typeToNodes.computeIfAbsent(dicType, k -> new ArrayList<>()).add(node);
        }

        // 2. 根节点：dic_type=0（level=1）
        List<Node> rootCandidates = typeToNodes.get(0);
        if (rootCandidates == null || rootCandidates.isEmpty()) {
            throw new RuntimeException("未找到根节点（dic_type=0）");
        }
        Node root = rootCandidates.get(0); // 假设根节点唯一
        root.setParentId("0");

        // 3. 递归关联各级节点的上下级
        linkChildren(root, typeToNodes);
        return root;
    }

    // 为指定节点关联子节点（子节点的dic_type = 当前节点的dic_type + 1）
    private static void linkChildren(Node parentNode, Map<Integer, List<Node>> typeToNodes) {
        int parentDicType = parentNode.getLevel() - 1; // 父节点的dic_type
        int childDicType = parentDicType + 1; // 子节点的dic_type（当前层级+1）

        // 获取所有可能的子节点（同属childDicType层级）
        List<Node> candidateChildren = typeToNodes.get(childDicType);
        if (candidateChildren == null || candidateChildren.isEmpty()) {
            return; // 没有子节点，直接返回
        }

        // 匹配子节点：子节点的code前缀必须是父节点的code（如11的父节点是1，111的父节点是11）
        String parentCode = parentNode.getCode();
        for (Node child : candidateChildren) {
            if (child.getCode().startsWith(parentCode)) {
                // 建立关联
                child.setParentId(parentCode);
                parentNode.addChild(child);
                // 递归为子节点关联它的子节点
                linkChildren(child, typeToNodes);
            }
        }
    }

    // 打印树形结构（可视化测试）
    private static void printTree(Node node, int depth) {
        // 缩进表示层级
      //  String indent = "  ".repeat(depth);
        StringBuilder indentBuilder = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            indentBuilder.append("  "); // 每次循环添加两个空格
        }
        String indent = indentBuilder.toString();

        System.out.println(indent + "[" + node.getCode() + "] " + node.getName()
                + " (level=" + node.getLevel() + ", parent=" + node.getParentId() + ")");

        // 递归打印子节点
        for (Node child : node.getChildren()) {
            printTree(child, depth + 1);
        }
    }

    // 读取Workbook（支持.xls和.xlsx）
    private static Workbook getWorkbook(String filePath) throws IOException {
        FileInputStream fis = new FileInputStream(new File(filePath));
        if (filePath.endsWith(".xlsx")) {
            return new XSSFWorkbook(fis);
        } else {
            return new HSSFWorkbook(fis);
        }
    }

    // 安全获取单元格值
    private static String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue().trim();
            case NUMERIC:
                // 处理数字类型（如整数编码）
                return String.valueOf((int) cell.getNumericCellValue());
            default:
                return "";
        }
    }
}
